﻿using UnityEngine;
using Unity.Entities;
using Unity.Transforms;
using Unity.Mathematics;

namespace Jinndev.ECS {

    public static class ECSUtil {

        public static void SetPosition(this ref float4x4 matrix, float3 position) {
            float4 c3 = matrix.c3;
            c3.x = position.x;
            c3.y = position.y;
            c3.z = position.z;
            matrix.c3 = c3;
        }

        public static void SetPosition(this ref LocalToWorld localToWorld, float3 position) {
            float4 c3 = localToWorld.Value.c3;
            c3.x = position.x;
            c3.y = position.y;
            c3.z = position.z;
            localToWorld.Value.c3 = c3;
            //localToWorld.Value = float4x4.TRS(position, localToWorld.Rotation, new float3(1));
        }

        public static void Translate(this ref LocalToWorld localToWorld, float3 delta) {
            float4 c3 = localToWorld.Value.c3;
            c3.x += delta.x;
            c3.y += delta.y;
            c3.z += delta.z;
            localToWorld.Value.c3 = c3;
        }

        public static void Translate(this ref LocalToWorld localToWorld, float2 delta) {
            float4 c3 = localToWorld.Value.c3;
            c3.x += delta.x;
            c3.y += delta.y;
            localToWorld.Value.c3 = c3;
        }

        public static void SafeAddComponent<T>(EntityManager entityManager, Entity entity) {
            if (!entityManager.HasComponent<T>(entity)) {
                entityManager.AddComponent<T>(entity);
            }
        }

        public static void SafeSetComponentData<T>(EntityManager entityManager, Entity entity, T data) where T : struct, IComponentData {
            if (!entityManager.HasComponent<T>(entity)) {
                entityManager.AddComponentData<T>(entity, data);
            }
            else {
                entityManager.SetComponentData<T>(entity, data);
            }
        }

        public static void SafeRemoveComponent<T>(EntityManager entityManager, Entity entity) where T : struct, IComponentData {
            if (!entityManager.HasComponent<T>(entity)) {
                entityManager.RemoveComponent<T>(entity);
            }
        }

        public static bool TryGetComponentData<T>(EntityManager entityManager, Entity entity, out T component) where T : struct, IComponentData {
            if (entityManager.HasComponent<T>(entity)) {
                component = entityManager.GetComponentData<T>(entity);
                return true;
            }
            component = default;
            return false;
        }

        public static bool TryGetSharedComponentData<T>(EntityManager entityManager, Entity entity, out T component) where T : struct, ISharedComponentData {
            if (entityManager.HasComponent<T>(entity)) {
                component = entityManager.GetSharedComponentData<T>(entity);
                return true;
            }
            component = default;
            return false;
        }

        public static DynamicBuffer<T> GetOrAddBuffer<T>(EntityManager entityManager, Entity entity) where T : struct, IBufferElementData {
            if (entityManager.HasComponent<T>(entity)) {
                return entityManager.GetBuffer<T>(entity);
            }
            else {
                return entityManager.AddBuffer<T>(entity);
            }
        }

        public static Entity CreateChildEntity(EntityManager entityManager, Entity entity, EntityArchetype archetype) {
            Entity child = entityManager.CreateEntity(archetype);
            SafeSetComponentData(entityManager, child, new Parent { Value = entity });
            return child;
        }

        public static Entity TryGetParent(EntityManager entityManager, Entity entity) {
            if (entityManager.HasComponent<Parent>(entity)) {
                return entityManager.GetComponentData<Parent>(entity).Value;
            }
            return Entity.Null;
        }

        public static void SetTranslation(EntityManager entityManager, Entity entity, float3 position) {
            entityManager.SetComponentData(entity, new Translation { Value = position });
        }

        public static void SetLocaltoWorld(EntityManager entityManager, Entity entity, float3 position) {
            entityManager.SetComponentData(entity, new LocalToWorld {
                Value = new float4x4(quaternion.identity, position)
            });
        }

    }


}